WebSocket接口初体验 |
您所在的位置:网站首页 › postman websocket接口 › WebSocket接口初体验 |
前言 这两天在调试一个WebSocket的接口,折腾了一天的时间终于弄好了。现在对WebSocket的相关知识点做一个记录。主要从如下几个方面进行介绍。 WebSocket的概念HTTP请求是基于请求响应的模式,永远是客户端请求服务器端,是单向的请求。如果服务器端有连续的状态变化,客户端就需要通过轮询的方式去获知。也就是每隔一段时间,就发出一个询问,了解服务器有没有新消息,轮询的效率比较低,非常浪费资源。 WebSocket的最大特点就是服务器可以主动向客户端推送消息,客户端也可以主动向服务器端发送消息,是真正的双向平等通信,也就是全双工通信。 建立一个WebSocket连接,客户端浏览器首先要向服务器发起一个HTTP请求,这个请求和通常的HTTP请求不同,包含了一些附加头信息。 客户端请求 GET / HTTP/1.1Request URL: ws://localhost:8080/webSocketServer/websocket/testnameConnection: UpgradeHost: localhost:8080Origin: http://localhost:63342Pragma: no-cacheSec-WebSocket-Extensions: permessage-deflate; client_max_window_bitsSec-WebSocket-Key: oxTUjq93ipRDk4gXWhi+mg==Sec-WebSocket-Version: 13Upgrade: websocket服务器响应 Connection: upgradeDate: Sat, 03 Oct 2020 03:26:03 GMTSec-WebSocket-Accept: Jjxh2cOWicbJdcdZ3rhcAeNdoHQ=Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15Upgrade: websocketConnection 必须设置Upgrade,表示客户端希望连接升级。 Upgrade字段必须设置WebSocket,表示希望升级到Websocket协议。 Sec-WebSocket-Key 是随机的字符串,服务器会用这些数据来构造出一个SHA-1的信息摘要,把" Sec-WebScoket-Key"加上一个特殊字符串"oxTUjq93ipRDk4gXWhi+mg=="然后计算 SHA-1 摘要,之后进行 BASE-64编码,将结果做为 “Sec-WebSocket-Accept” 头的值,返回给客户端。如此操作,可以尽量避免普通 HTTP 请求被误认为Websocket 协议。 服务器解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的WebSocket连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接,http和WebSocket的连接生命周期如下: 首先我们需要引入WebSocket的starter模块,这个模块的作用开启WebSocket的模块功能,如下所示: org.springframework.boot spring-boot-starter-websocket 配置基础类依赖引入之后,我们需要配置ServerEndpointExporter的Bean,这个Bean作用是我们可以通过@ServerEndpoint注解声明WebSocket。 @Componentpublic class WebSocketConfig { /** * ServerEndpointExporter作用 * 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); }} 编写websocket的服务端接口准备工作做好之后,接下来就是编写WebSocket的服务端的接口,在此Controller中,定义了Session类,通过它来给客户端发送消息,通过ConcurrentHashMap来存储当前连接的客户端。 @Component@ServerEndpoint("/websocket/{name}")public class WebSocketController { /** * 与某个客户端的连接对话,需要通过它来给客户端发送消息 */ private Session session; /** * 标识当前连接客户端的用户名 */ private String name;private static ConcurrentHashMap websocketSet = new ConcurrentHashMap(); @OnOpen public void OnOpen(Session session, @PathParam(value = "name") String name) { this.session = session; this.name = name; //name是用来表示唯一客户端,如果需要指定发送,需要指定发送通过name来区分 websocketSet.put(name, this); log.info("[WebSocket]连接成功,当前连接人数为={}", websocketSet.size()); } @OnClose public void OnClose() { websocketSet.remove(this.name); log.info("[WebSocket]退出成功,当前连接人数为={}", websocketSet.size()); } @OnMessage public void OnMessage(String message) { log.info("[WebSocket]收到消息={}", message); groupSending("客户端的消息我已经收到了"); } public void groupSending(String message) { for (String name : websocketSet.keySet()) { try { websocketSet.get(name).session.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } }} 我们通过@ServerEndpoint注解标识这个类是一个WebSocket接口,通过@OnOpen标记的方法进行WebSocket的服务连接,通过@OnMessage标记的方法进行消息的接收,以及响应消息给客户端,其中给客户端发送消息websocketSet.get(name).session.getBasicRemote().sendText(message); getBasicRemote()的方法表示通过同步的方式发送消息,getAsyncRemote()的方法表示通过异步的方式发送消息。通过@OnClose标记的方法进行服务的关闭。 客户端的调用客户端的调用有好几种方式,我们可以通过JS的方式,实例化WebSocketClient的方式,运用OkHttpClient的方式,下面就分别对这三种方式的调用做一个介绍。 通过JS的方式调用服务var websocket = null; if ('WebSocket' in window) { //用于创建WebSocket对象,webSocketTest对应的是java类的注解值。 websocket = new WebSocket("ws://localhost:8080/webSocketServer/websocket/testname"); } else { alert("当前浏览器不支持"); }// 连接发生错误的时候回调方法; websocket.onerror = function () { alert("连接错误"); }// 连接成功时建立回调方法 websocket.onopen = function () { //WebSocket已连接上,使用send()方法发送数据 alert("连接成功"); };// 收到消息的回调方法 websocket.onmessage = function (msg) { setdivInnerHTML(msg.data); }; //连接关闭的回调方法 websocket.onclose = function () { closed(); alert("关闭成功"); };function closed() { websocket.close(); alert("点击关闭"); } function send() { var message=document.getElementById("message").value; //注意引号内的内容应该是文本框的id而不能是name alert(message); websocket.send(message); //给后台发送数据 } 同样的首先是实例化一个WebSocket对象,然后通过onmessage回调方法接受服务端响应的结果,通过send方法给后台发送数据。 通过实例化WebSocketClient的方式引入依赖 org.java-websocket Java-WebSocket 1.3.5同样的我们需要进行客户端的配置,也就是实例化一个WebSocketClient的实例。主要是建立连接,发送消息。 @Bean public WebSocketClient webSocketClient() { try { WebSocketClient webSocketClient = new WebSocketClient(new URI("ws://localhost:8080/webSocketServer/websocket/name1"), new Draft_6455()) { @Override public void onOpen(ServerHandshake handshakedata) { log.info("[websocket] 连接成功"); } @Override public void onMessage(String message) { log.info("[websocket] 收到消息={}", message); } @Override public void onClose(int code, String reason, boolean remote) { log.info("[websocket] 退出连接"); } @Override public void onError(Exception ex) { log.info("[websocket] 连接错误={}", ex.getMessage()); } }; webSocketClient.connect(); return webSocketClient; } catch (URISyntaxException e) { e.printStackTrace(); } return null; }然后在Controller中通过WebSocketClient的send方法给服务器端发送消息,如下所示; @RestController@RequestMapping("/websocket")public class WebSocketClientController { @Autowired private WebSocketClient webSocketClient;@RequestMapping("/index") public String sendMessage(String message) { webSocketClient.send("测试消息"); return "消息发送成功"; }} 这是一种通过后端接口调用服务的方式,当然我们还有其他的方式,就像下面这种通过OkHttpClient的方式。 通过OkHttpClient的方式同样的还是先引入依赖。 com.squareup.okhttp3 okhttp 3.9.1然后定义一个类,继承WebSocketListener,用于建立连接,发送消息。 public class OkHttpClientService extends WebSocketListener { private String result = null;@Override public void onOpen(WebSocket webSocket, Response response) { super.onOpen(webSocket, response); webSocket.send("需要发送的请求数据"); } @Override public void onMessage(WebSocket webSocket, String text) { super.onMessage(webSocket, text); //其中text是接收到的参数 result = text; } public static void main(String[] args) { OkHttpClient client = new OkHttpClient.Builder() //设置超时时间是5秒 .connectTimeout(5, TimeUnit.MINUTES) .build(); //http的请求对应的就是websocket中的ws;https的请求对应的就是websocket中的wss String url = "ws://localhost:8080/webSocketServer/websocket/name2"; //实例化Request对象 Request request = new Request.Builder().url(url).build(); OkHttpClientService okHttpClientService = new OkHttpClientService(); client.newWebSocket(request, okHttpClientService); //轮询获取结果 while (okHttpClientService.result == null) { } System.out.println("接口响应的结果=" + okHttpClientService.result); }} 同样的,还是重写了onOpen方法和onMessage方法,onOpen方法用来发送消息,onMessage方法用来接收服务器的请求。如果是异步的消息的话,我们就需要轮询获取结果。 总结本文简单首先介绍了WebSocket的基本概念和相关特点,WebSocket是一个全双工通信的协议,它支持客户端向服务端发送消息, 也支持服务端向客户端发送消息, 一次握手,可以多次发送消息。接着就是介绍了在SpringBoot中如何整合WebSocket的相关功能。实现了一个服务端和客户端。 源码地址https://github.com/XWxiaowei/web_socket_demo.git 参考https://www.jianshu.com/p/9aa969dd1b4d
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |